home *** CD-ROM | disk | FTP | other *** search
GIMP Script-Fu Script | 2005-06-30 | 13.2 KB | 365 lines |
- ;; spyrogimp.scm -*-scheme-*-
- ;; Draws Spirographs, Epitrochoids and Lissajous Curves.
- ;; More info at http://netword.com/*spyrogimp
- ;; Version 1.2
- ;;
- ;; Copyright (C) 2003 by Elad Shahar <elad@wisdom.weizmann.ac.il>
- ;;
- ;; This program is free software; you can redistribute it and/or
- ;; modify it under the terms of the GNU General Public License
- ;; as published by the Free Software Foundation; either version 2
- ;; of the License, or (at your option) any later version.
- ;;
- ;; This program is distributed in the hope that it will be useful,
- ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ;; GNU General Public License for more details.
- ;;
- ;; You should have received a copy of the GNU General Public License
- ;; along with this program; if not, write to the Free Software
- ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- ; Internal function to draw the spyro.
- (define (script-fu-spyrogimp-internal img drw
- x1 y1 x2 y2 ; Bounding box.
- type ; = 0 (Spirograph), 1 (Epitrochoid), 2(Lissajous) .
- shape ; = 0 (Circle), 1 (Frame), >2 (Polygons) .
- oteeth iteeth ; Outer and inner teeth.
- margin hole-ratio
- start-angle ; 0 <= start-angle < 360 .
- tool ; = 0 (Pencil), 1 (Brush), 2 (Airbrush) .
- brush
- color-method ; = 0 (Single color), 1 (Grad. Loop Sawtooth), 2 (Grad. Loop triangle) .
- color ; Used when color-method = Single color .
- grad ; Gradient used in Gradient color methods.
- )
-
- ; Find minimum number n such that it is divisible by both a and b.
- ; (least common multiplier)
- (define (calc-min-mult a b)
- (let* ((c 1) (fac 2) (diva 0) (divb 0))
- (while ( <= fac (max a b) )
- (set! diva ( = 0 (fmod (/ a fac) 1) ) )
- (set! divb ( = 0 (fmod (/ b fac) 1) ) )
-
- (if diva (set! a (/ a fac)))
- (if divb (set! b (/ b fac)))
-
- (if (or diva divb)
- (set! c (* c fac))
- (set! fac (+ 1 fac)) )
- )
- c
- )
- )
-
-
- ; This function returns a list of samples according to the gradient.
- (define (get-gradient steps color-method grad)
- (if (= color-method 1)
- ; option 1
- ; Just return the gradient
- (gimp-gradient-get-uniform-samples grad (min steps 50) FALSE)
-
- ; option 2
- ; The returned list is such that the gradient appears two times, once
- ; in the normal order and once in reverse. This way there are no color
- ; jumps if we go beyond the edge
- (let* (
- ; Sample the gradient into array "gr".
- (gr (gimp-gradient-get-uniform-samples grad (/ (min steps 50) 2) FALSE))
-
- (grn (car gr)) ; length of sample array.
- (gra (cadr gr)) ; array of color samples (R1,G1,B1,A1, R2,....)
-
- ; Allocate array gra-new of size (2 * grn) - 8,
- ; but since each 4 items is actually one (RGBA) tuple,
- ; it contains 2x - 2 entries.
- (grn-new (+ grn grn -8))
- (gra-new (cons-array grn-new 'double))
-
- (gr-index 0)
- (gr-index2 0)
- )
-
- ; Copy original array gra to gra_new.
- (while (< gr-index grn)
- (aset gra-new gr-index (aref gra gr-index))
- (set! gr-index (+ 1 gr-index))
- )
-
- ; Copy second time, but in reverse
- (set! gr-index2 (- gr-index 8))
- (while (< gr-index grn-new)
- (aset gra-new gr-index (aref gra gr-index2))
- (set! gr-index (+ 1 gr-index))
- (set! gr-index2 (+ 1 gr-index2))
-
- (if (= (fmod gr-index 4) 0)
- (set! gr-index2 (- gr-index2 8))
- )
- )
-
- ; Return list.
- (list grn-new gra-new)
- )
- )
- )
-
-
- (let* ((steps (+ 1 (calc-min-mult oteeth iteeth)))
- (*points* (cons-array (* steps 2) 'double))
-
- (ot 0) ; current outer tooth
- (cx 0) ; Current x,y
- (cy 0)
-
- ; If its a polygon or frame, how many sides does it have.
- (poly (if (= shape 1) 4 ; A frame has four sides.
- (if (> shape 1) (+ shape 1) 0)))
-
- (2pi (* 2 *pi*))
-
- (drw-width (- x2 x1))
- (drw-height (- y2 y1))
- (half-width (/ drw-width 2))
- (half-height (/ drw-height 2))
- (midx (+ x1 half-width))
- (midy (+ y1 half-height))
-
- (hole (* hole-ratio
- (- (/ (min drw-width drw-height) 2) margin)
- )
- )
- (irad (+ hole margin))
-
- (radx (- half-width irad)) ;
- (rady (- half-height irad)) ;
-
- (gradt (get-gradient steps color-method grad))
- (grada (cadr gradt)) ; Gradient array.
- (gradn (car gradt)) ; Number of entries of gradients.
-
- ; Indexes
- (grad-index 0) ; for array: grada
- (point-index 0) ; for array: *points*
- (index 0)
- )
-
-
- ; Do one step of the loop.
- (define (calc-and-step!)
- (let* (
- (oangle (* 2pi (/ ot oteeth)) )
- (shifted-oangle (+ oangle (* 2pi (/ start-angle 360))) )
- (xfactor (cos shifted-oangle))
- (yfactor (sin shifted-oangle))
- (lenfactor 1)
- (ofactor (/ (+ oteeth iteeth) iteeth))
-
- ; The direction of the factor changes according
- ; to whether the type is a sypro or an epitcorhoid.
- (mfactor (if (= type 0) (- ofactor) ofactor))
- )
-
- ; If we are drawing a polygon then compute a contortion
- ; factor "lenfactor" which deforms the standard circle.
- (if (> poly 2)
- (let* (
- (pi4 (/ *pi* poly))
- (pi2 (* pi4 2))
-
- (oanglemodpi2 (fmod (+ oangle
- (if (= 1 (fmod poly 2))
- 0 ;(/ pi4 2)
- 0
- )
- )
- pi2
- ))
- )
- (set! lenfactor (/ ( if (= shape 1) 1 (cos pi4) )
- (cos
- (if (< oanglemodpi2 pi4)
- oanglemodpi2
- (- pi2 oanglemodpi2)
- )
- )
- )
- )
- )
- )
-
- (if (= type 2)
- (begin ; Lissajous
- (set! cx (+ midx
- (* half-width (cos shifted-oangle)) ))
- (set! cy (+ midy
- (* half-height (cos (* mfactor oangle))) ))
- )
- (begin ; Spyrograph or Epitrochoid
- (set! cx (+ midx
- (* radx xfactor lenfactor)
- (* hole (cos (* mfactor oangle) ) ) ))
- (set! cy (+ midy
- (* rady yfactor lenfactor)
- (* hole (sin (* mfactor oangle) ) ) ))
- )
- )
-
- ;; Advance teeth
- (set! ot (+ ot 1))
- ))
-
-
- ;; Draw all the points in *points* with appropriate tool.
- (define (flush-points len)
-
- (if (= tool 0)
- (gimp-pencil drw len *points*) ; Use pencil
- (if (= tool 1)
- (gimp-paintbrush-default drw len *points*); use paintbrush
- (gimp-airbrush-default drw len *points*) ; use airbrush
- )
- )
-
- ; Reset points array, but copy last point to first
- ; position so it will connect the next time.
- (aset *points* 0 (aref *points* (- point-index 2)))
- (aset *points* 1 (aref *points* (- point-index 1)))
- (set! point-index 2)
- )
-
- ;;
- ;; Execution starts here.
- ;;
-
- (gimp-context-push)
-
- (gimp-image-undo-group-start img)
-
- ; Set new color, brush, opacity, paint mode.
- (gimp-context-set-foreground color)
- (gimp-context-set-brush (car brush))
- (gimp-context-set-opacity (* 100 (car (cdr brush))))
- (gimp-context-set-paint-mode (car (cdr (cdr (cdr brush)))))
-
- (while (< index steps)
-
- (calc-and-step!)
-
- (aset *points* point-index cx)
- (aset *points* (+ point-index 1) cy)
- (set! point-index (+ point-index 2))
-
- ; Change color and draw points if using gradient.
- (if (< 0 color-method) ; use gradient.
- (if (< (/ (+ grad-index 4) gradn) (/ index steps))
- (begin
- (gimp-context-set-foreground
- (list
- (* 255 (aref grada grad-index))
- (* 255 (aref grada (+ 1 grad-index)) )
- (* 255 (aref grada (+ 2 grad-index)) )
- )
- )
- (gimp-context-set-opacity (* 100 (aref grada (+ 3 grad-index) ) ) )
- (set! grad-index (+ 4 grad-index))
-
- ; Draw points
- (flush-points point-index)
- )
- )
- )
-
- (set! index (+ index 1))
- )
-
-
- ; Draw remaining points.
- (flush-points point-index)
-
- (gimp-image-undo-group-end img)
- (gimp-displays-flush)
-
- (gimp-context-pop)))
-
-
- ; This routine is invoked by a dialog.
- ; It is the main routine in this file.
- (define (script-fu-spyrogimp img drw
- type shape
- oteeth iteeth
- margin hole-ratio start-angle
- tool brush
- color-method color grad)
- (let*
-
- ; Get current selection to determine where to draw.
- (
- (bounds (cdr (gimp-selection-bounds img)))
- (x1 (car bounds))
- (y1 (cadr bounds))
- (x2 (caddr bounds))
- (y2 (car (cdddr bounds)))
- )
-
- (set! oteeth (trunc (+ oteeth 0.5)))
- (set! iteeth (trunc (+ iteeth 0.5)))
-
- (script-fu-spyrogimp-internal img drw
- x1 y1 x2 y2
- type shape
- oteeth iteeth
- margin hole-ratio start-angle
- tool brush
- color-method color grad)
- )
- )
-
-
- (script-fu-register "script-fu-spyrogimp"
- _"_Spyrogimp..."
- _"Draws Spirographs, Epitrochoids and Lissajous Curves. More info at http://netword.com/*spyrogimp"
- "Elad Shahar <elad@wisdom.weizmann.ac.il>"
- "Elad Shahar"
- "June 2003"
- "RGB*, INDEXED*, GRAY*"
- SF-IMAGE "Image" 0
- SF-DRAWABLE "Drawable" 0
-
- SF-OPTION _"Type" '(_"Spyrograph"
- _"Epitrochoid"
- _"Lissajous")
- SF-OPTION _"Shape" '(_"Circle"
- _"Frame"
- _"Triangle"
- _"Square"
- _"Pentagon"
- _"Hexagon"
- _"Polygon: 7 sides"
- _"Polygon: 8 sides"
- _"Polygon: 9 sides"
- _"Polygon: 10 sides")
- SF-ADJUSTMENT _"Outer teeth" '(86 1 120 1 10 0 0)
- SF-ADJUSTMENT _"Inner teeth" '(70 1 120 1 10 0 0)
- SF-ADJUSTMENT _"Margin (pixels)" '(0 -10000 10000 1 10 0 1)
- SF-ADJUSTMENT _"Hole ratio" '(0.4 0.0 1.0 0.01 0.1 2 0)
- SF-ADJUSTMENT _"Start angle" '(0 0 359 1 10 0 0)
-
- SF-OPTION _"Tool" '(_"Pencil"
- _"Brush"
- _"Airbrush")
- SF-BRUSH _"Brush" '("Circle (01)" 1.0 -1 0)
-
- SF-OPTION _"Color method" '(_"Solid Color"
- _"Gradient: Loop Sawtooth"
- _"Gradient: Loop Triangle")
- SF-COLOR _"Color" '(0 0 0)
- SF-GRADIENT _"Gradient" "Deep Sea")
-
- (script-fu-menu-register "script-fu-spyrogimp"
- _"<Image>/Script-Fu/Render")
-